From: Keir Fraser Date: Tue, 13 May 2008 09:16:54 +0000 (+0100) Subject: x86: Avoid deep recusrsion when destroying a domain and reaping pagetables. X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14215^2~17 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https://%22%22/%22http:/www.example.com/cgi/%22https:/%22%22?a=commitdiff_plain;h=96ce955d7f38dd1f92337cbdabe261b74deb3e87;p=xen.git x86: Avoid deep recusrsion when destroying a domain and reaping pagetables. From: Jan Beulich Signed-off-by: Keir Fraser --- diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 5c8fe5f557..6dd3f33310 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -1725,6 +1725,27 @@ static int relinquish_memory( if ( test_and_clear_bit(_PGC_allocated, &page->count_info) ) put_page(page); +#ifdef DOMAIN_DESTRUCT_AVOID_RECURSION + /* + * Forcibly drop reference counts of page tables above top most (which + * were skipped to prevent long latencies due to deep recursion - see + * the special treatment in free_lX_table()). + */ + y = page->u.inuse.type_info; + if ( (type < PGT_root_page_table) && + unlikely(((y + PGT_type_mask) & + (PGT_type_mask|PGT_validated)) == type) ) + { + BUG_ON((y & PGT_count_mask) >= + (page->count_info & PGC_count_mask)); + while ( y & PGT_count_mask ) + { + put_page_and_type(page); + y = page->u.inuse.type_info; + } + } +#endif + /* * Forcibly invalidate top-most, still valid page tables at this point * to break circular 'linear page table' references. This is okay @@ -1896,6 +1917,11 @@ int domain_relinquish_resources(struct domain *d) /* fallthrough */ case RELMEM_done: +#ifdef DOMAIN_DESTRUCT_AVOID_RECURSION + ret = relinquish_memory(d, &d->page_list, PGT_l1_page_table); + if ( ret ) + return ret; +#endif break; default: diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index ef51a4181f..6839d53b50 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -1320,6 +1320,11 @@ static void free_l3_table(struct page_info *page) l3_pgentry_t *pl3e; int i; +#ifdef DOMAIN_DESTRUCT_AVOID_RECURSION + if ( d->arch.relmem == RELMEM_dom_l3 ) + return; +#endif + pl3e = map_domain_page(pfn); for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ ) @@ -1343,6 +1348,11 @@ static void free_l4_table(struct page_info *page) l4_pgentry_t *pl4e = page_to_virt(page); int i; +#ifdef DOMAIN_DESTRUCT_AVOID_RECURSION + if ( d->arch.relmem == RELMEM_dom_l4 ) + return; +#endif + for ( i = 0; i < L4_PAGETABLE_ENTRIES; i++ ) if ( is_guest_l4_slot(d, i) ) put_page_from_l4e(pl4e[i], pfn); diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h index 006910c299..87058ee3cd 100644 --- a/xen/include/asm-x86/config.h +++ b/xen/include/asm-x86/config.h @@ -41,6 +41,14 @@ #define CONFIG_HOTPLUG 1 #define CONFIG_HOTPLUG_CPU 1 +/* + * Avoid deep recursion when tearing down pagetables during domain destruction, + * causing dom0 to become unresponsive and Xen to miss time-critical softirq + * deadlines. This will ultimately be replaced by built-in preemptibility of + * get_page_type(). + */ +#define DOMAIN_DESTRUCT_AVOID_RECURSION 1 + #define HZ 100 #define OPT_CONSOLE_STR "vga"